package com.hewep.view;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.SplitPane;
import javafx.scene.control.ToolBar;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.DirectoryChooser;

import com.hewep.Main;
import com.hewep.kit.FileKit;

public class ConfigPane extends AnchorPane {

	private Main main;
	@FXML
	private SplitPane splitPane;
	@FXML
	private TreeView<FileItem> srcView;
	@FXML
	private TreeView<FileItem> destView;
	private String folderOpenImg = "res/images/folder-open.png";
	private String folderCloseImg = "res/images/folder-close.png";
	private String fileImg = "res/images/file.png";

	private String filePath;
	private List<FileItem> fileItems = new ArrayList<FileItem>();
	private Map<String, TreeItem<FileItem>> srcItemMap = new HashMap<String, TreeItem<FileItem>>();
	private Map<String, TreeItem<FileItem>> destItemMap = new HashMap<String, TreeItem<FileItem>>();
	private double mouseDragOffsetX = 0;
	private double mouseDragOffsetY = 0;

	public ConfigPane(Main main) {
		this.main = main;
		this.init();
	}

	public void init() {
		FXMLLoader fxml = new FXMLLoader(getClass().getResource(
				"res/config.fxml"));
		fxml.setController(this);
		try {
			Parent parent = fxml.load();
			this.getChildren().add((Node) parent);

			ToolBar toolBar = (ToolBar) parent.lookup("#toolbar");

			toolBar.setOnMousePressed(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					mouseDragOffsetX = event.getSceneX();
					mouseDragOffsetY = event.getSceneY();
				}
			});
			toolBar.setOnMouseDragged(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					main.getStage().setX(event.getScreenX() - mouseDragOffsetX);
					main.getStage().setY(event.getScreenY() - mouseDragOffsetY);
				}
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@FXML
	private void onOpen(ActionEvent event) {

		DirectoryChooser directoryChooser = new DirectoryChooser();
		directoryChooser.setTitle("源目录");
		directoryChooser.setInitialDirectory(new File(System
				.getProperty("user.home")));
		File dialog = directoryChooser.showDialog(main.getStage());

		if (dialog != null) {
			srcItemMap.clear();
			destItemMap.clear();
			destView.setRoot(null);
			filePath = dialog.getName();
			Node rootIcon = new ImageView(new Image(getClass()
					.getResourceAsStream(folderOpenImg)));
			TreeItem<FileItem> root = new TreeItem<FileItem>(new FileItem("",
					dialog), rootIcon);
			root.setExpanded(true);
			showTreeItems(root, dialog);
			srcView.setRoot(root);
			srcView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);

			srcView.setOnMouseClicked(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					// TODO Auto-generated method stub
					if (event.getClickCount() == 2) {
						for (FileItem fileItem : fileItems) {
							fileItem.setOpen(false);
						}
						TreeItem<FileItem> item = (TreeItem<FileItem>) srcView
								.getSelectionModel().getSelectedItem();

						addItem(item);
						TreeItem<FileItem> src = handleMap();
						src.setExpanded(true);
						destView.setRoot(src);
					}
				}
			});

			destView.setOnMouseClicked(new EventHandler<MouseEvent>() {
				@Override
				public void handle(MouseEvent event) {
					// TODO Auto-generated method stub
					if (event.getClickCount() == 2) {

						if (srcItemMap.isEmpty()) {
							return;
						}
						TreeItem<FileItem> item = (TreeItem<FileItem>) destView
								.getSelectionModel().getSelectedItem();

						removeChildItems(item);
						srcItemMap.remove(item.getValue().getFileName());

						TreeItem<FileItem> dest = handleMap();
						if (dest != null && !dest.isLeaf()) {
							dest.setExpanded(true);
						}
						destView.setRoot(dest);
					}
				}
			});
		}
	}

	@FXML
	private void onSave(ActionEvent event) {
		DirectoryChooser directoryChooser = new DirectoryChooser();
		directoryChooser.setTitle("补丁文件");
		File file = directoryChooser.showDialog(main.getStage());
		if (file != null) {
			for (FileItem fileItem : fileItems) {
				if (fileItem.isSelect()) {
					String srcPath = fileItem.getFile().getAbsolutePath();
					System.out.println(srcPath);
					String destPath = file.getAbsolutePath() + File.separator
							+ srcPath.substring(srcPath.indexOf(filePath));
					File srcFile = new File(srcPath);
					File destFile = new File(destPath);

					if (srcFile.isDirectory()) {
						FileKit.createFolder(destPath);
					} else {
						FileKit.copyFile(srcPath, destPath);
					}
				}
			}

		}
	}

	@FXML
	private void onClose(ActionEvent event) {
		Platform.exit();
	}

	public TreeItem<FileItem> handleMap() {
		destItemMap = new HashMap<String, TreeItem<FileItem>>();
		Set<String> keySet = srcItemMap.keySet();
		for (String key : keySet) {
			if (!destItemMap.containsKey(key)) {
				TreeItem<FileItem> treeItem = srcItemMap.get(key);
				TreeItem<FileItem> item = new TreeItem<FileItem>(treeItem.getValue());
				destItemMap.put(key, item);
			}
		}

		TreeItem<FileItem> root = null;
		try {
			List<Map.Entry<String, TreeItem<FileItem>>> items =
				    new ArrayList<Map.Entry<String, TreeItem<FileItem>>>(destItemMap.entrySet());
			
			Collections.sort(items, new Comparator<Map.Entry<String, TreeItem<FileItem>>>() {   
				public int compare(Entry<String, TreeItem<FileItem>> arg0,
						Entry<String, TreeItem<FileItem>> arg1) {
					File f0 = arg0.getValue().getValue().getFile();
					File f1 = arg1.getValue().getValue().getFile();
					if (f0.isDirectory() && f1.isFile())
				          return -1;
					if (f0.isFile() && f1.isDirectory())
				          return 1;
					return f0.getName().compareToIgnoreCase(f1.getName());
				}
			}); 
			
			for (Map.Entry<String, TreeItem<FileItem>> itemEntry : items) {
				
				TreeItem<FileItem> item = itemEntry.getValue();

				if (item.getValue().isOpen()) {
					item.setExpanded(true);
				}
				FileItem fileItem = item.getValue();
				TreeItem<FileItem> parentItem = destItemMap.get(fileItem.getParent());
				if (parentItem != null) {
					parentItem.getChildren().add(item);
				} else {
					root = item;
				}
			}
			for (Map.Entry<String, TreeItem<FileItem>> itemEntry : items) {
				TreeItem<FileItem> item = itemEntry.getValue();

				if (item.isLeaf()) {
					item.setGraphic(new ImageView(new Image(getClass()
							.getResourceAsStream(fileImg))));
				} else {
					item.setGraphic(new ImageView(new Image(getClass()
							.getResourceAsStream(folderCloseImg))));
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return root;
	}

	public void addItem(TreeItem<FileItem> item) {
		FileItem fileItem = item.getValue();
		fileItem.setSelect(true);

		if (!item.isLeaf()) {
			fileItem.setOpen(true);
		}
		String fileName = fileItem.getFileName();
		if (srcItemMap.get(fileName) == null) {

			srcItemMap.put(fileName,
					new TreeItem<FileItem>(fileItem, item.getGraphic()));
		}
		addParentItems(item);
		addChildItems(item);
	}

	// 移除子节点
	public void removeChildItems(TreeItem<FileItem> item) {
		ObservableList<TreeItem<FileItem>> children2 = item.getChildren();
		for (TreeItem<FileItem> treeItem : children2) {
			removeChildItems(treeItem);
			srcItemMap.remove(treeItem.getValue().getFileName());
		}
	}

	// 添加父节点
	public void addParentItems(TreeItem<FileItem> item) {
		TreeItem<FileItem> parent2 = item.getParent();
		if (parent2 == null) {
			return;
		}
		FileItem fileItem = parent2.getValue();
		fileItem.setSelect(true);
		fileItem.setOpen(true);
		String fileName = fileItem.getFileName();
		if (srcItemMap.get(fileName) == null) {
			srcItemMap.put(fileName, new TreeItem<FileItem>(fileItem));
		}
		addParentItems(parent2);
	}

	// 添加 子节点
	public void addChildItems(TreeItem<FileItem> item) {

		ObservableList<TreeItem<FileItem>> childrens = item.getChildren();

		for (TreeItem<FileItem> treeItem : childrens) {
			FileItem fileItem = treeItem.getValue();
			String fileName = fileItem.getFileName();
			if (srcItemMap.get(fileName) == null) {
				srcItemMap.put(fileName, new TreeItem<FileItem>(fileItem));
			}
			addChildItems(treeItem);
		}
	}

	/**
	 * 递归调用 生成treeview
	 * @param root
	 * @param file
	 */
	public void showTreeItems(TreeItem<FileItem> root, File file) {
		List<File> files = Arrays.asList(file.listFiles());
		if (files == null) {
			return;
		}
		Collections.sort(files, new Comparator<File>() {
			public int compare(File o1, File o2) {
				if (o1.isDirectory() && o2.isFile())
			          return -1;
				if (o1.isFile() && o2.isDirectory())
			          return 1;
				return o1.getName().compareToIgnoreCase(o2.getName());
			}
		});
		
		for (File file2 : files) {
			if (file2.getName().startsWith(".")) {
				continue;
			}
			FileItem fileItem = new FileItem(root.getValue().getFileName(),
					file2);
			fileItems.add(fileItem);

			TreeItem<FileItem> item = new TreeItem<FileItem>(fileItem);
			if (file2.isDirectory()) {
				Node folderCloseIcon = new ImageView(new Image(getClass()
						.getResourceAsStream(folderCloseImg)));
				item.setGraphic(folderCloseIcon);

				showTreeItems(item, file2);
			} else {
				Node fileIcon = new ImageView(new Image(getClass()
						.getResourceAsStream(fileImg)));
				item.setGraphic(fileIcon);
			}
			root.getChildren().add(item);
		}
	}
}
